﻿using PhotoKiosk.Model;
using PhotoKiosk.Model.Device;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;

namespace PhotoKiosk.DataAccess
{
    public class SystemData
    {
        private const int k_Uninitialized = -5;

        public string ReceptionFormatFileLocation
        {
            get 
            { 
                return Path.Combine(Environment.CurrentDirectory, "ReceptionFormat.txt"); 
            }
            set
            {

            }
        }

        private int _kioskID = k_Uninitialized;
        public int KioskID
        {
            set
            {
                _kioskID = value;
                UpdatFieldInConfigFile("KioskId", value.ToString());
            }
            get
            {
                if (_kioskID == k_Uninitialized)
                {
                    int tempKioskId;
                    if (int.TryParse(ConfigurationManager.AppSettings["KioskId"], out tempKioskId))
                    {
                        _kioskID = tempKioskId;
                    }
                }
                return _kioskID;
            }
        }

        public IDevice ConnectedDevice
        {
            get;
            private set;
        }

        public Order Order
        {
            get;
            private set;
        }

        private string _ordersLocationSave = string.Empty;
        public string OrdersLocationSave
        {
            get
            {
                if (_ordersLocationSave == string.Empty)
                {
                    _ordersLocationSave = ConfigurationManager.AppSettings["OrderLocationSave"];
                }
                return _ordersLocationSave;
            }
            set
            {
                _ordersLocationSave = value;
                UpdatFieldInConfigFile("OrderLocationSave", value);
            }
        }

        private bool m_printReception;
        public bool PrintReception
        {
            set
            {
                if (m_printReception != value)
                {
                    UpdatFieldInConfigFile("printReception", value.ToString());
                    m_printReception = value;
                }
            }
            get
            {
                if (!bool.TryParse(ConfigurationManager.AppSettings["printReception"], out m_printReception))
                {
                    m_printReception = false;
                }
                return m_printReception;
            }
        }

        private List<string> m_imageExtensions = null;
        public List<string> ImageExtensions
        {
            get
            {
                if (m_imageExtensions == null)
                {
                    m_imageExtensions = new List<string>();
                    m_imageExtensions = (ConfigurationManager.AppSettings["Image-Extension"].Split(new char[] { ';' })).ToList<string>();
                }
                return m_imageExtensions;
            }
        }

        private List<PhotoKiosk.Model.PaperSize> m_paperSizes = null;
        public List<PhotoKiosk.Model.PaperSize> PaperSizes
        {
            get
            {
                if (m_paperSizes == null)
                {
                    List<string> ff = (ConfigurationManager.AppSettings["PaperSize"].Split(new char[] { ';' })).ToList<string>();
                    m_paperSizes = new List<PhotoKiosk.Model.PaperSize>();
                    foreach (string s in ff)
                    {
                        m_paperSizes.Add(PhotoKiosk.Model.PaperSize.Parse(s));
                    }
                }
                return m_paperSizes;
            }
            set
            {
                StringBuilder s = new StringBuilder();
                m_paperSizes = value;
                foreach (PhotoKiosk.Model.PaperSize pz in m_paperSizes)
                {
                    s.Append(PhotoKiosk.Model.PaperSize.ParseToXML(pz) + ";");
                }
                s = s.Remove(s.Length-1, 1);
                UpdatFieldInConfigFile("PaperSize", s.ToString());
            }
        }

        private List<string> m_imageExtensionsAcceptedByPrinter = null;
        public List<string> ImageExtensionsAcceptedByPrinter
        {
            get
            {
                if (m_imageExtensionsAcceptedByPrinter == null)
                {
                    m_imageExtensionsAcceptedByPrinter = new List<string>();
                    m_imageExtensionsAcceptedByPrinter = (ConfigurationManager.AppSettings["Image-Extensions-Accepted-By-Printer"].Split(new char[] { ';' })).ToList<string>();
                }
                return m_imageExtensionsAcceptedByPrinter;
            }
            set
            {
                StringBuilder s = new StringBuilder();
                m_imageExtensionsAcceptedByPrinter = value;
                foreach (string str in m_imageExtensionsAcceptedByPrinter)
                {
                    s.Append(str + ";");
                }
                s = s.Remove(s.Length - 1, 1);
                UpdatFieldInConfigFile("Image-Extensions-Accepted-By-Printer", s.ToString());
            }
        }

        private String m_systemCloseCode = String.Empty;
        public String SystemCloseCode
        {
            set
            {
                if (m_systemCloseCode != value)
                {          
                    UpdatFieldInConfigFile("SystemCloseCode", value.ToString());
                    m_systemCloseCode = value;
                }
            }
            get
            {
                if (m_systemCloseCode == String.Empty)
                {
                    m_systemCloseCode = ConfigurationManager.AppSettings["SystemCloseCode"];
                }
                return m_systemCloseCode;
            }
        }

        private string sampleImagesPath = null;
        public string SampleImagesPath
        {
            get
            {
                if (sampleImagesPath == null)
                {
                    sampleImagesPath = Path.Combine(Directory.GetCurrentDirectory(), ConfigurationManager.AppSettings["SampleImages"]);
                }
                return sampleImagesPath;
            }
        }

        private int m_minimunOrderPrice = k_Uninitialized;
        public int MinimunOrderPrice
        {
            set
            {
                if (m_minimunOrderPrice != value)
                {
                    m_minimunOrderPrice = value;
                    UpdatFieldInConfigFile("MinimumOrderPrice", value.ToString());
                }
            }
            get
            {
                if (m_minimunOrderPrice == k_Uninitialized)
                {
                    if (!int.TryParse(ConfigurationManager.AppSettings["MinimumOrderPrice"], out m_minimunOrderPrice))
                    {
                        m_minimunOrderPrice = 0;
                    }
                }
                return m_minimunOrderPrice;
            }
        }

        private int m_nextOrderId = k_Uninitialized;
        public int NextOrderId
        {
            get
            {
                if (m_nextOrderId == k_Uninitialized)
                {
                    int tempNextOrderId;
                    if (int.TryParse(ConfigurationManager.AppSettings["OrderIdNumber"], out tempNextOrderId))
                    {
                        m_nextOrderId = tempNextOrderId;
                    }
                }
                return m_nextOrderId;
            }
            set
            {
                if (m_nextOrderId != value)
                {
                    m_nextOrderId = value;
                    UpdatFieldInConfigFile("OrderIdNumber", value.ToString());
                }
            }
        }

        private CultureInfo m_currentLanguage;
        public CultureInfo CurrentLanguage
        {
            get
            {
                if(m_currentLanguage == null)
                {
                    m_currentLanguage = new CultureInfo(ConfigurationManager.AppSettings["CurrentLanguage"]);
                }
                return m_currentLanguage;
            }
            set
            {
                if (m_currentLanguage != value)
                {          
                    UpdatFieldInConfigFile("CurrentLanguage", value.Name);
                     m_currentLanguage = value;
                }
            }
        }

        public void StartNewOrder()
        {
            Order = new Order(NextOrderId);
            NextOrderId++;
        }

        public void SetCustomer(Customer i_customer)
        {
            Order.Customer = i_customer;
        }

        public bool SetConnectedDevice(IDevice i_Device)
        {
            if (i_Device != null && i_Device.Connect() == true)
            {
                ConnectedDevice = i_Device;
                if (ConnectedDevice is SampleFolder)
                {
                    ((SampleFolder)ConnectedDevice).Connect(SampleImagesPath);
                }
                else
                {
                    ConnectedDevice.Connect();
                }
                ConnectedDevice.LoadAllPhotos(ImageExtensions);
                return true;
            }
            else
            {
                return false;
            }
        }

        private void SavePhotosToDirectory()
        {
            string m_path = Path.Combine(OrdersLocationSave, Order.IDNumber.ToString(), Order.PaperSize.ToString());
            if (System.IO.Directory.Exists(m_path) == false)
            {
                System.IO.Directory.CreateDirectory(m_path);
            }
            foreach (Photo s in ConnectedDevice.AllPhotos())
            {
                for (int i = 0; i < s.NumberOfCopies; i++)
                {
                    if (ImageExtensionsAcceptedByPrinter.Contains(s.FileExtension))
                    {
                        System.IO.File.Copy(s.FilePath, m_path + "\\" + i + "-" + System.IO.Path.GetFileName(s.FilePath), true);
                    }
                    else
                    {
                        ConvertEnyImageToJPG(s.FilePath, m_path, i);
                    }
                }
            }
        }
  
        private void CreateAndPrintReception()
        {
            StreamReader receptionFormat = new StreamReader(ReceptionFormatFileLocation, Encoding.UTF8);
            String receptionFormatString = receptionFormat.ReadToEnd();
            receptionFormat.Close();

            receptionFormatString = receptionFormatString.Replace("[KioskID]", KioskID.ToString());
            receptionFormatString = receptionFormatString.Replace("[OrderID]", Order.IDNumber.ToString());
            receptionFormatString = receptionFormatString.Replace("[Time]", Order.Time.ToString());
            receptionFormatString = receptionFormatString.Replace("[UserName]", Order.Customer.Name.ToString());
            receptionFormatString = receptionFormatString.Replace("[UserPhone]", Order.Customer.PhoneNumber.ToString());
            int numberOfPhotos = 0;
            foreach (Photo p in ConnectedDevice.AllPhotos())
            {
                numberOfPhotos += p.NumberOfCopies;
            }
            receptionFormatString = receptionFormatString.Replace("[NumOfPhotos]", numberOfPhotos.ToString());
            receptionFormatString = receptionFormatString.Replace("[PaperSize]", Order.PaperSize.ToString());
            receptionFormatString = receptionFormatString.Replace("[PaperType]", Order.PaperType.ToString());
            receptionFormatString = receptionFormatString.Replace("[PaperFrame]", Order.PaperFrame.ToString());

            float price = numberOfPhotos * Order.PaperSize.Price;
            string pricestr = RegionInfo.CurrentRegion.CurrencySymbol + " " + price.ToString();
            receptionFormatString = receptionFormatString.Replace("[Price]", pricestr);

            //Print reception
            if (PrintReception)
            {
                printFile(receptionFormatString);
            }

            //Save reception
            string m_receptionPath = Path.Combine(OrdersLocationSave, Order.IDNumber.ToString(), Order.IDNumber.ToString() + ".txt");
            createTextFile(m_receptionPath, receptionFormatString);
        }

        public float OrderPrice()
        {
            float _tempPrice = 0;
            foreach (Photo p in ConnectedDevice.AllPhotos())
            {
                _tempPrice += (p.NumberOfCopies * Order.PaperSize.Price);
            }
            if (_tempPrice < MinimunOrderPrice && _tempPrice > 0)
            {
                _tempPrice = MinimunOrderPrice;
            }
            return _tempPrice;
        }

        public void FinishOrder()
        {
            SavePhotosToDirectory();
            CreateAndPrintReception();
        }

        private static bool printFile(string i_Path)
        {
            PrintDocument p = new PrintDocument();
            p.PrintPage += delegate(object sender1, PrintPageEventArgs e1)
            {
                e1.Graphics.DrawString(i_Path, new System.Drawing.Font("Times New Roman", 12), new SolidBrush(System.Drawing.Color.Black), new RectangleF(0, 0, p.DefaultPageSettings.PrintableArea.Width, p.DefaultPageSettings.PrintableArea.Height));

            };
            try
            {
                p.Print();
            }
            catch
            {
                return false;
            }
            return true;
        }

        private static void createTextFile(String i_Path, String i_TextData)
        {
            var file = new System.IO.StreamWriter(i_Path);
            file.WriteLine(i_TextData);
            file.Close();
        }

        public void UpdatFieldInConfigFile(string i_key, string i_value)
        {
            // Open App.Config of executable
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            // Add an Application Setting.
            config.AppSettings.Settings.Remove(i_key);
            config.AppSettings.Settings.Add(i_key, i_value);

            // Save the changes in App.config file.
            config.Save(ConfigurationSaveMode.Modified);

            // Force a reload of a changed section.
            ConfigurationManager.RefreshSection("appSettings");
        }

        public static void ConvertEnyImageToJPG(string i_SourceFile, string i_DestinationFolder, int i_NumberOfCopy)
        {

            ImageCodecInfo jgpEncoder = getEncoder(ImageFormat.Jpeg);
            Bitmap source = new Bitmap(System.Drawing.Image.FromFile(i_SourceFile));
            // Create an Encoder object based on the GUID
            // for the Quality parameter category.
            System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;

            // Create an EncoderParameters object.
            // An EncoderParameters object has an array of EncoderParameter
            // objects. In this case, there is only one
            // EncoderParameter object in the array.
            EncoderParameters myEncoderParameters = new EncoderParameters(1);

            EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 10000L);
            myEncoderParameters.Param[0] = myEncoderParameter;

            Uri u = new Uri(i_SourceFile);

            string dest = i_DestinationFolder + "\\" + i_NumberOfCopy + Path.GetFileNameWithoutExtension(i_SourceFile) + ".jpg";
            source.Save(dest, jgpEncoder, myEncoderParameters);
        }

        private static ImageCodecInfo getEncoder(ImageFormat format)
        {
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
            foreach (ImageCodecInfo codec in codecs)
            {
                if (codec.FormatID == format.Guid)
                {
                    return codec;
                }
            }
            return null;
        }
    }
}
